/*
 * Author: aple
 *
 * Created on 2015年10月9日, 上午10:07
 */

#ifndef SIMP_log2_M_H
#define	SIMP_log2_M_H

#include "stdint.h"
#include "rtctime.h"

#ifdef	__cplusplus
extern "C" {
#endif	

	typedef struct
	{
		uint32_t blocks;
		uint32_t blocks_per_page;
		uint32_t site_start;
		uint32_t site_next;
	} simp_log2_info_type;

	typedef struct
	{
		void (*save)(void);
		void (*save_verify)(void);
		void (*init)(void);
		uint32_t (*site_to_addr)(uint32_t site);
		void (*read)(uint32_t site, void *pdat);
		int32_t (*site_fore)(int32_t site, int32_t fore_amount);
		int32_t (*quick_search)(sig_time_type time, int8_t mode);
		int32_t (*head_search)(int32_t num, int32_t *site_des);
	}simp_log2_api_type;
	
	typedef struct
	{
		uint32_t addr_base;                          //必须对齐page_size边界
		uint32_t total_size;                         //必须为page_size的整数倍，且至少为4倍
		uint16_t page_size;                          //必须为2^n
		uint16_t dat_size;                           //必须为2^n，且最小为4
		void *pdat;                                  //必须为4字节对齐的地址
		simp_log2_info_type * info;
		void(*Erase)(uint32_t AddrBase);                /*擦除*/
		void(*Program)(uint32_t Addr, uint32_t *dat, uint16_t Len);    /*编程*/
		void(*Read)(uint32_t Addr, uint32_t *dat, uint16_t Len);   /*读取*/
		const simp_log2_api_type * api;
	} simp_log2_type;

	void simp_log2_init(const simp_log2_type * cfg);
	uint32_t simp_log2_site_to_addr(const simp_log2_type * cfg, uint32_t site);
		
	void simp_log2_save(const simp_log2_type * cfg);
	void simp_log2_save_verify(const simp_log2_type * cfg);
	void simp_log2_read(const simp_log2_type * cfg, uint32_t site, void *pdat);
	
	int32_t simp_log2_site_fore(const simp_log2_type * cfg, int32_t site, int32_t fore_amount);
	int32_t simp_log2_head_search(const simp_log2_type * cfg, int32_t num, int32_t *site_des);
	
	/*-----------------------------------------------------------------------------------------------------*
	 * 快速搜索，内部采用二分搜索法，从start到next-1区间
	 * mode: 0(未命中目标时返回-1)，-1(未命中目标时返回小于目标值的位置)，1(未命中目标时返回大于目标值的位置)
	 * return 返回-1代表未搜到指定结果， +数指向搜索结果位置
	 *-----------------------------------------------------------------------------------------------------*/
	int32_t simp_log2_quick_search(const simp_log2_type * cfg, sig_time_type time, int8_t mode);

	/*-----------------------------------------------------------------------------------------------------*
	 * API
	 *-----------------------------------------------------------------------------------------------------*/
	#define simp_log2_api_make(obj)											\
	void obj##_save(void){ simp_log2_save(&obj);}							\
	void obj##_save_verify(void){ simp_log2_save_verify(&obj);}				\
	void obj##_init(void ){ simp_log2_init(&obj);}							\
	uint32_t obj##_site_addr(uint32_t site)									\
		{ return simp_log2_site_to_addr(&obj, site);}						\
	void obj##_read(uint32_t site, void *pdat)								\
		{ simp_log2_read(&obj, site, pdat);}								\
	int32_t obj##_site_fore(int32_t site, int32_t fore_amount)				\
		{ return simp_log2_site_fore(&obj, site, fore_amount);}				\
	int32_t obj##_quick_search(sig_time_type time, int8_t mode)				\
		{ return simp_log2_quick_search(&obj, time, mode);}					\
	int32_t obj##_head_search(int32_t num, int32_t *site_des)				\
		{ return simp_log2_head_search(&obj, num, site_des);}				\
	const simp_log2_api_type  obj##_api = {									\
		obj##_save,															\
		obj##_save_verify,													\
		obj##_init,															\
		obj##_site_addr,													\
		obj##_read,															\
		obj##_site_fore,													\
		obj##_quick_search,													\
		obj##_head_search													\
	}

#define simp_log2_api_ref(obj)	extern const simp_log_api_type obj##_api
#define simp_log2_api_name(obj)	&obj##_api
	
#ifdef	__cplusplus
}
#endif

#endif	/* SIMP_log2_M_H */
